var mg = require('../db/userdb')
var pr_mg = require('../db/processdb')
var msg = require('../tool/message')
var redis = require('../db/redis')
var pu = require('../tool/public')


class approve {

    /**
     * 节点审核钩子
     * @param process_id 当前流程ID  Objictid
     * @param template  表单模板 array
     * @param user    [userid,username]   Objectid
     * @param status    审核状态 Number  1通过 2驳回
     * @param describe  描述     string
     * @param nodeid    节点ID   Objectid
     * @param reject_id    节点ID   Objectid
     */
    async approve_succesc (process_id, template, user, status, describe, nodeid, reject_id) {
        /*1、找出模板内容*/



        /*2、查看当前节点类型  完结：做归档 审核：更改状态并计算下一节点 推送：添加消息或者邮件*/


        let process = await pr_mg.findOne('process', { _id: process_id })

        var isnext = true
        for (var i = 0; i < process.user.length; i++) { //审核校验 避爬虫
            for (var j = 0; j < user.length; j++) {
                // console.log(process.user[i].userid.toString(), user[j].userid.toString())
                if (process.user[i].userid.toString() == user[j].userid.toString()) {
                    isnext = false
                }
            }
        }
        // if (!nodeid && reject_id) {
        //     nodeid = reject_id
        // }
        let nodeinfo = getnode(process.node, nodeid)//当前节点
        if (isnext && (nodeinfo[0].type != 'stop' && nodeinfo[0].type != 'start') && status == 1) { //自动审核节点跳过
            return
        }


        if (nodeinfo[0].type == 'stop') {
            let _ids = process._id.toString()
            process.status = 1
            delete process._id
            process.readyuserid = []
            process.user = []
            process.process_id = mg.ObjectID(_ids)
            let info = await pr_mg.insertOne('process_file', process)
            await pr_mg.update('process_record', { process_id: process._id }, { $set: { status: 1 } }, false, true)
            if (info.insertedId) { //插入成功后再删除
                pr_mg.deleteOne('process', { _id: mg.ObjectID(_ids) })
            }
            return
        }
        let nextnode = getnextnode(process.lin, status == 3 ? reject_id : nodeid, template)//下一根线数据
        let nextnodeinfo = getnode(process.node, nextnode.targetId) //下一节点信息
        if (nextnode == false) { //无法找到下个节点无法继续进行
            return
        }
        //type: 1 我发起的  2 抄送我的 3 我审核过的
        var inserinfo = {
            team_id: process.team_id,
            process_id: process._id,
            template_uuid: process.template_uuid,
            process_uuid: process.process_uuid,
            template_name: process.template_name,
            process_name: process.process_name,
            template_version: process.template_version,
            process_version: process.process_version,
            startUserid: process.startUserid,
            startUserName: process.startUserName,
            time: new Date().getTime(),
            date: process.date,
            startTime: process.startTime,
            msg: describe,
            status: 0,
            userid: mg.ObjectID(user[0].userid),
            username: user[0].username,
            nodeid: nodeid,
            nextnodeid: nextnode.targetId
        }
        console.log('当前节点', JSON.stringify(nodeinfo))
        console.log('下节点', JSON.stringify(nextnodeinfo))
        /*审核做记录*/
        switch (nodeinfo[0].type) {
            case 'start': //如果是开始 开始只能单一进行
                inserinfo.userid = mg.ObjectID(user[0].userid)
                inserinfo.username = user[0].username
                inserinfo.type = 1
                /*修改节点内容*/
                var nodeinfo_all = process.node
                nodeinfo_all[nodeinfo[1]].status = status
                if (!nodeinfo_all[nodeinfo[1]].user) {
                    nodeinfo_all[nodeinfo[1]].user = []
                }
                nodeinfo_all[nodeinfo[1]].user = [{ userid: user[0].userid, username: user[0].username, status: status }]
                await pr_mg.update('process_record', { process_id: process._id, userid: mg.ObjectID(user[0].userid) }, { $set: inserinfo }, true, false)//记录
                await pr_mg.updateOne('process', { _id: process._id }, { //修改节点记录
                    $set: {
                        node: nodeinfo_all,
                        readyuserid: [{ userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status, msg: describe }],
                    },
                    $push: {
                        record: { userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status, msg: describe, time: +new Date() },
                    }
                })
                //流程往后走
                nodenext(nextnodeinfo[0], process, status, nodeid)
                break
            case 'notice': //通知 通知可以同时进行
                /*修改节点内容*/
                var nodeinfo_all = process.node
                nodeinfo_all[nodeinfo[1]].status = status
                if (!nodeinfo_all[nodeinfo[1]].user) {
                    nodeinfo_all[nodeinfo[1]].user = []
                }
                var inserlist = []
                var record = process.record

                var userlist_array = []//发邮件

                for (var i = 0; i < user.length; i++) {
                    inserinfo.userid = mg.ObjectID(user[i].userid)
                    inserinfo.username = user[i].username
                    userlist_array.push(user[i].userid)
                    inserinfo.type = 2
                    nodeinfo_all[nodeinfo[1]].user.push({ userid: user[0].userid, username: user[0].username, status: status }) //节点中处理用户
                    record.push({ userid: mg.ObjectID(user[i].userid), username: user[i].username, status: status, time: +new Date(), msg: describe })
                    inserlist.push(inserinfo)
                    msg.sendemail(user[i].userid, {
                        title: '您好 您有新代办' + process.template_name,
                        username: '系统通知',
                        time: +new Date(),
                        status: 0,
                        message: '代办' + process.template_name + '\r\n发起人：' + process.startUserName + '\r\n发起时间:' + pu.formatDateTime(1, process.date)
                    })
                    if (nodeinfo[0].notice_type > 0) { //需要发邮件
                        msg.sendemail(user[i].userid, {
                            title: '您好 您有新代办' + process.template_name,
                            username: '系统通知',
                            time: +new Date(),
                            status: 0,
                            message: '代办' + process.template_name + '\r\n发起人：' + process.startUserName + '\r\n发起时间:' + pu.formatDateTime(1, process.date)
                        })
                    }

                }
                await pr_mg.insertMany('process_record', inserlist) //添加记录
                await pr_mg.updateOne('process', { _id: process._id }, { //修改节点记录
                    $set: { node: nodeinfo_all, record: record },
                })
                //流程往后走
                nodenext(nextnodeinfo[0], process, status, nodeid)
                break
            case 'approve': //如果是审核 审核只能是单人进行
                /*修改记录信息*/
                inserinfo.userid = mg.ObjectID(user[0].userid)
                inserinfo.username = user[0].username
                inserinfo.type = 3
                /* 修改节点内容 并节点中新增审核过的人*/
                var nodeinfo_all = process.node
                nodeinfo_all[nodeinfo[1]].status = status
                if (!nodeinfo_all[nodeinfo[1]].user) {
                    nodeinfo_all[nodeinfo[1]].user = []
                }
                nodeinfo_all[nodeinfo[1]].user.push({ userid: user[0].userid, username: user[0].username, status: status })

                if (status == 4) { //作废
                    inserinfo.type = 4
                    await pr_mg.update('process_record', { process_id: process._id, userid: mg.ObjectID(user[0].userid) }, { $set: inserinfo }, true, false)//记录
                    let _ids = process._id.toString()
                    process.status = 4
                    await pr_mg.update('process_record', { process_id: process._id }, { $set: { status: 4 } }, false, true)
                    delete process._id
                    let info = await pr_mg.insertOne('process_file', process)
                    if (info.insertedId) { //插入成功后再删除
                        pr_mg.deleteOne('process', { _id: mg.ObjectID(_ids) })
                    }
                } else if (status == 2 || status == 3) {//审核不通过
                    process.status = status
                    await pr_mg.update('process_record', { process_id: process._id }, { $set: { status: status } }, false, true)
                    await pr_mg.updateOne('process', { _id: process._id }, { //修改原始记录
                        $set: {
                            node: nodeinfo_all,
                            readyuserid: [{ userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status }]
                        },
                        $push: {
                            record: { userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status, msg: describe, time: +new Date() },
                        }
                    })
                    await pr_mg.update('process_record', { process_id: process._id, userid: mg.ObjectID(user[0].userid) }, { $set: inserinfo }, true, false)//记录

                    //流程往后走
                    nodenext(nextnodeinfo[0], process, status, nodeid, reject_id)

                } else if (status == 1 && nodeinfo.is_all_agree === 0) { //只需要一个人
                    await pr_mg.update('process_record', { process_id: process._id }, inserinfo, true, false) //添加记录
                    await pr_mg.updateOne('process', { _id: process._id }, { //修改原始记录
                        $set: {
                            node: nodeinfo_all,
                            readyuserid: [{ userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status }]
                        },
                        $push: {
                            record: { userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status, msg: describe, time: +new Date() }
                        }
                    })
                    //流程往后走
                    nodenext(nextnodeinfo[0], process, status, nodeid)
                    break
                } else { //需要全部人
                    await pr_mg.update('process_record', { process_id: process._id, userid: mg.ObjectID(user[0].userid) }, { $set: inserinfo }, true, false)//记录
                    await pr_mg.updateOne('process', { _id: mg.ObjectID(process._id) }, { //修改原始记录
                        $set: {
                            node: nodeinfo_all,
                        },
                        $push: {
                            record: { userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status, msg: describe, time: +new Date() },
                            readyuserid: { userid: mg.ObjectID(user[0].userid), username: user[0].username, status: status },
                        }
                    })
                    if (process.readyuserid.length + 1 >= process.user.length) {
                        nodenext(nextnodeinfo[0], process, status, nodeid)
                    }
                }
                break
            case 'stop': //结束 做归档 并且移除流程库
                let _ids = process._id.toString()
                process.status = 1
                delete process._id
                let info = await pr_mg.insertOne('process_file', process)
                if (info.insertedId) { //插入成功后再删除
                    pr_mg.deleteOne('process', { _id: mg.ObjectID(_ids) })
                }
        }
    }
}

/**
 * nodenext() 节点信息往下走  需要修改当前节点处理人和设置下节点
 * @param index 节点所在位置
 * @param process 流程记录
 * @param status 节点审核状态  1通过 2驳回
 * @param nodeid  如果是驳回需要传该id
 *
 */
async function nodenext (nextnode, process, status, lastnodeid, reject_id) {
    let prclass = new approve()

    if (nextnode.type == 'stop' && status == 1) {
        prclass.approve_succesc(process._id, process.template, [], 1, '完结', nextnode.id)
    } else if (status == 1) { //上个节点是通过 继续往下走 通过
        let userlist = await getuserlist(nextnode, process, lastnodeid) //获取到下节点全部人
        if (userlist.length) {
            var newinfo = {}
            newinfo.date = +new Date()
            newinfo.user = userlist //所处理的人
            newinfo.current_nodeid = nextnode.id //所在节点
            newinfo.next_nodeid = lastnodeid //下节点
            newinfo.readyuserid = []
            for (var i = 0; i < userlist.length; i++) {
                msg.sendmsg([userlist[i].userid.toString()], {
                    title: '您好 您有新代办' + process.template_name,
                    username: '系统通知',
                    time: +new Date(),
                    status: 0,
                    message: '代办' + process.template_name + '\r\n发起人：' + process.startUserName + '\r\n发起时间:' + pu.formatDateTime(1, process.date)
                })
            }

            await pr_mg.updateOne('process', { _id: process._id }, { $set: newinfo })
        }
        /*如果下一节点是通知或者下一节点是结束 自动审核*/
        if (nextnode.type == 'notice') {
            prclass.approve_succesc(process._id, process.template, userlist, 1, '抄送', nextnode.id)
        }
    } else if (status == 2 || status == 3) { // 审核不通过
        let nodeinfo = getnode(process.node, reject_id)//当前节点
        nextnode = nodeinfo[0]
        let userlist = await getuserlist(nextnode, process, reject_id) //获取到下节点全部人
        if (nextnode.type == 'start') { //驳回到开始节点
            userlist = [{
                'userid': process.startUserid,
                'username': process.startUserName
            }]
        }
        if (userlist.length) {
            var newinfo = {}
            newinfo.user = userlist //所处理的人
            newinfo.current_nodeid = nextnode.id //所在节点
            newinfo.date = +new Date()
            newinfo.readyuserid = []
            console.log(newinfo.user)

            await pr_mg.update('process', { _id: process._id }, { $set: newinfo }, false, false)

        }
    }

}

// [{  节点信息模板
//     "id": "node_server_162813090041810700",
//     "style": "left: 331px; top: 288px;",
//     "name": "     抄送节点",
//     "className": "node node-notice canver-node",
//     "type": "notice",
//     "notice_type": "", //推送类型 0 代办 1邮件 2代办和邮件
//     "status": "",  //审批状态
//     "remarks": "",//审批备注
//     "node_name": "",//节点自定义名称
//     "is_all_agree": "",//审批方式 0单人 1所有人
//     "examine_list": [{_id: "", name: "" ,type:0}],//  0 指定人  1角色 2部门  3岗位 4 节点上级主管
//     "user": [ //处理过的用户
//         {id: "", username: "", status: ""}//审核状态
//     ]
// }]

/*通过节点信息和用户id找到下节点用户*/
async function getuserlist (nodeinfo, process, lastnodeid) {
    var userlist = []

    for (var i = 0; i < nodeinfo.examine_list.length; i++) {
        let list = await getuserlistinfo(nodeinfo.examine_list[i], process, Number(nodeinfo.examine_list[i].type), lastnodeid)
        userlist = userlist.concat(list)
    }
    console.log('下一节点审核人', userlist)
    return userlist

}


async function getuserlistinfo (data, process, approve_type, nodeid) {
    var userlist = []
    switch (approve_type) {
        case 0: //指定人
            userlist.push({ userid: mg.ObjectID(data._id), username: data.name })
            break
        case 1 : //指定角色
            // role: { $elemMatch: { userid: mg.ObjectID(userid) } }
            var where = { team_id: mg.ObjectID(process.team_id), role: { $elemMatch: { $eq: mg.ObjectID(data._id) } } }
            let userinfo = await mg.find('team_users', where)
            for (var i = 0; i < userinfo.length; i++) {
                userlist.push({ userid: userinfo[i]._id, username: userinfo[i].name })
            }
            break
        case 2://部门 找部门负责人
            let departementinfo = await mg.findOne('department', { _id: mg.ObjectID(data._id) })
            if (departementinfo.admin_id) {
                userlist.push({ userid: departementinfo.admin_id, username: departementinfo.admin_name })
            }
            break
        case 4: //上节点上级
            /*
            * 1、通过设置的节点找领导  在前面节点中找到userid
            * */
            let node = process.node
            var last_userlist = [] //处理过的人

            for (var i = 0; i < node.length; i++) {
                if (node[i].id == nodeid) {//找到节点取出上节点处理过的人
                    last_userlist = node[i].user
                }

            }
            var where = {
                '$or': []
            }
            for (var i = 0; i < last_userlist.length; i++) {
                where['$or'].push({ _id: mg.ObjectID(last_userlist[i].userid) })
            }
            let info = await mg.find('team_users', where)
            for (var i = 0; i < info.length; i++) {
                userlist.push({ userid: mg.ObjectID(info[i].leader_id), username: info[i].leader_name })
            }
            break
    }
    return userlist


}

/*通过节点ID获取节点信息*/

/*返回数组 节点内容和节点下标*/
function getnode (nodelist, nodeid) {
    for (var i = 0; i < nodelist.length; i++) {
        if (nodelist[i].id == nodeid) {
            return [nodelist[i], i]
        }
    }
}

/*找出下一根线走向*/
function getnextnode (linlist, nodeid, template) {
    var satisfylsit = []//所有链接当前节点的线
    for (var k = 0; k < linlist.length; k++) {
        if (linlist[k].sourceId == nodeid) {
            satisfylsit.push(linlist[k])
        }
    }
    var where = {}
    for (var i = 0; i < template.length; i++) {
        where[template[i].id] = template[i].propValue
    }
    for (var i = 0; i < satisfylsit.length; i++) {
        try {
            if (satisfylsit[i].select.new_condition) {
                if (eval(satisfylsit[i].select.new_condition)) { //满足条件
                    return satisfylsit[i]
                }
            } else {
                satisfylsit[0] = satisfylsit[i]
            }
        } catch (e) {
            console.error('条件内容不正确', JSON.stringify(satisfylsit[i]))
            console.error(e)
        }
    }
    if (satisfylsit[0]) {
        return satisfylsit[0]
    } else {
        return false
    }
}


module.exports = new approve()
